#include "MobileCountrySdkCallback.h"
#include "MobileCountrySdkAPI.h"
#include "cc_api/cc_api.h"
#include "cc_api/cc_types.h"
#include "cc_api/cc_device.h"
#include "md5sum.h"

#include "DevLed.h"
#include "DevWifi.h"
#include "Qrcode.h"
#include "PowerManager.h"
#include "Video.h"
#include "Audio.h"
#include "app_common.h"
#include <unistd.h>
#include "UpgradeRecovery.h"
#include "System.h"
#include "ping.h"
#include "DevSocSub.h"

#define  UPGRADE_FILE   "/ramfs/upgrade.bin"
#define  UPGRADE_INFO   "/config/wjaUpgradeUrl"

#ifdef __cplusplus
extern "C" {
#endif

#define MC_LIVE_PREVIEW_MAX_TIME_SEC    (165) //165s + 15s休眠缓冲时间
char static gs_mcLivePreviewState = 0;

static int g_keeplive = 0;
static int g_doorbell_hd = 0;
static int g_register_status = 0;

int QRCode_OriData_Handle(char *pdata, int length)
{
	QrcodePushData(pdata, length);
}

FILE *fp = NULL;
static size_t writefile_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
	int len = size * nmemb;
	int written = len;

	if (fp)
	{
		fwrite(ptr, nmemb, size, fp);
		printf("download size[%dkb]", len / 1024);
	}

	return written;
}

int writeUpgradeInfo(const char *upgradeUrl, const char *md5, int fileLenght)
{
#if 0
	FILE *fp = NULL;
	char upgradeInfo[1024] = { 0 };
	fp = fopen(UPGRADE_INFO, "wb");
	if (fp)
	{
		sprintf(upgradeInfo, "%s %s %d", upgradeUrl, md5, fileLenght);
		fwrite(upgradeInfo, 1, strlen(upgradeInfo), fp);
		fclose(fp);
	} 
#else
    UpgradeRecoverySetInfo(upgradeUrl, md5, fileLenght);
    UpgradeRecoverySetState(1);
#endif
	return 0;
}

static void Doorbell_quit_sleep()
{
    printf("quit sleep proc\n");
    g_keeplive = 0;
}

static void Doorbell_wakeup(cc_wakeup_type_e type)
{
	printf("\n\nDoorbell_wakeup\n\n");
    //低功耗设备，PIR唤醒，实际使用过程中唤醒操作在启动流程的基础上，调用cc_api_restore

    cc_detect_type_e  event;
    
    Doorbell_quit_sleep();                        //断开和保活服务器的连接（非必须）
    cc_api_restore(type, CC_WAKE_UP_REASON_TYPE_NULL);
    cc_api_start(); 
    if(type == CC_WAKE_UP_BY_RING)
    {
        event = CC_DETECT_RING;
    }
    else if(type == CC_WAKE_UP_BY_PIR)
    {
        event = CC_DETECT_PIR;
    }
    else
    {
        return;
    }
    cc_api_set_event(util_current_utc_time_ms(), event, CC_DETECT_PULSE, NULL);

}


/*低功耗设备连接心跳保活服务器*/
int connnect_heartbeat_server(cc_hb_config hbconfig, int* psockfd)
{
    struct sockaddr_in servaddr;
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family= AF_INET;
    servaddr.sin_port = htons(hbconfig.serverport[0].port);
    if(inet_pton(AF_INET, hbconfig.serverport[0].server, &servaddr.sin_addr) <= 0)
    {
        printf("inet_pton failed.\n");
        return -1;
    }

    *psockfd = socket(AF_INET,SOCK_STREAM, 0);

    if(connect(*psockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        printf("connect failed.\n");
        return -1;
    }
    printf("TCP connected successfully!\n");
    return 0;
}


/*低功耗设备维持和保活服务器的心跳连接*/
int interact_heartbeat_server(cc_hb_config hbconfig, int sockfd)
{
    fd_set rdset;
    fd_set wtset;
    struct timeval tv;
    int rlen;
    int ret = 0;
    uint64_t tnow = 0;
    char buffer[64] = {0};
    printf("enter into heartbeat loop.\n");

    while (g_keeplive)
    {
        tv.tv_sec = 1;
        tv.tv_usec = 0;

        FD_ZERO(&rdset);
        FD_ZERO(&wtset);
        FD_SET(sockfd, &rdset);
        
        if (tnow == 0 || util_current_utc_time_ms() - tnow >= hbconfig.interval * 1000)
        {
            tnow = util_current_utc_time_ms();
            printf("to send heartbeat request.\n");    //发送心跳包
            if (write(sockfd, hbconfig.heartbeatrequest, hbconfig.heartbeatrequestlen)
                    != hbconfig.heartbeatrequestlen)
                {
                    printf("TCP write error\n");
                    return -1;
                }
        }
        
        ret = select(sockfd+1, &rdset, NULL, NULL, &tv);
        if(ret == -1)
        {
            printf("TCP select error %s\n", strerror(errno));
            return -1;
        }
        else if(ret == 0)
        {
            printf("keep live...\n");
            continue;
        }

        if(FD_ISSET(sockfd, &rdset))
        {
_ReadAgain:
            rlen = read(sockfd, buffer, hbconfig.wakeuprequestlen);
            if (rlen > 0)
            {
                printf("TCP read %dB from server.\n", rlen);     //匹配收到的tcp包的报文
                if (rlen == hbconfig.wakeuprequestlen 
                	&& memcmp(buffer, hbconfig.wakeuprequest, hbconfig.wakeuprequestlen) == 0)
                {
                    printf("recv wakeup request\n", buffer);     //收到唤醒???                    return 0;
                }
                else
                {
                    printf("read other: %s\n", buffer);
                }
            }
            else if (rlen == 0)
            {
                printf("TCP read zero return!\n");
                return -1;
            }
            else
            {
                if (EINTR == errno)
                {
                    goto _ReadAgain;
                }
                else if (EWOULDBLOCK == errno || EAGAIN == errno)
                {
                    usleep(200);
                    continue;
                }
                else
                {
                    printf("TCP other error of socket read, %d!\n", errno);
                    return -1;
                }
            }
        }        
    }
    
    return -1;
}

/*启动低功耗设备和保活服务器的连接*/
static void *Doorbell_keep_live_pro(void* args)
{
    cc_hb_config config = *(cc_hb_config*)(args);

    printf("heartbeat pkg len:%d, wakeup pkg len:%d\n", config.heartbeatrequestlen, config.wakeuprequestlen);
    printf("heartbeat pkg interval:%d\n",config.interval);
    int i=0;
    for(;i<config.servernum;i++)    //如果有多个服务器，设备要和每个服务器都建立TCP连接
    {
        printf("keep live server:%s:%d\n",config.serverport[i].server, config.serverport[i].port);
    }
    int sockfd=-1;

    while (g_keeplive)
    {
        if (connnect_heartbeat_server(config, &sockfd) == 0)
        {
            if(interact_heartbeat_server(config, sockfd) == 0)
            {
                printf("receive remove wakeup request\n");
                //收到唤醒请求，主控板上电，启动SDK
                Doorbell_wakeup(CC_WAKE_UP_BY_APP_CLIENT);
                break;
            }
        }
        if (sockfd != -1)
        {
            close(sockfd);
            sockfd = -1;
        }
        sleep(1);
        printf("loop again\n");
    }
    if (sockfd != -1)
    {
        close(sockfd);
        sockfd = -1;
    }
    printf("end loop\n");
    return NULL;
}

/*低功耗wifi芯片建立和保活服务器的连接，进入休眠*/
static int Doorbell_start_sleep(cc_hb_config* config)
{
    static cc_hb_config scfg;
    memcpy(&scfg,config,sizeof(scfg));
    printf("Begin___\n");
    pthread_t pid;
    g_keeplive = 1;
    pthread_create(&pid, NULL, Doorbell_keep_live_pro, &scfg);

    pthread_detach(pid);
	PowerSetSocSleepTime(1, 3);
    printf("End___\n");

    return 0;
}

static void Doorbell_sleep()
{
    cc_hb_config config;
    memset(&config,0,sizeof(config));
    if(0 == cc_api_suspend(&config)) //获取保活服务器信???	
    {
        Doorbell_start_sleep(&config);  
    }
    cc_api_stop();                     //主控板下???   
}

int Doorbell_video_set_HD(int hd)
{
	uint32_t BitRate;
	RealTimeVideoDataFormat videoinfo;
	VIDEO_STREAM_ATTR_S stStreamAttr;

	videoinfo.codec = RT_CODEC_H264;
	videoinfo.colorDepth = 24;
	videoinfo.framerate = 15;
	videoinfo.frameInterval = 15 * 2;

	if (hd == 0)
	{
		BitRate = 160; //src:512 256
		videoinfo.width  = 640; //src:1280
		videoinfo.height = 360; //src:720
	}
	else if (hd == 1)
	{
		BitRate = 400; //src:800 512
		videoinfo.width  = 1280; //src:1920
		videoinfo.height = 720; //src:1080
	}

	memset(&stStreamAttr, 0, sizeof(stStreamAttr));
	stStreamAttr.bitrate = BitRate;
	stStreamAttr.width = videoinfo.width;
	stStreamAttr.height = videoinfo.height;
	stStreamAttr.framerate = videoinfo.framerate;

	int Ret = VideoGetOpsHandle()->set_resolution(0, stStreamAttr);
	if (Ret < 0) {
    		LOGE("set_resolution chn:%d failed\n", 0);
    		return -1;
	}  
}

int Doorbell_video_get_HD(void)
{
	return g_doorbell_hd;
}

int MC_get_register_status(void)
{
	return g_register_status;
}

int MobileCountryRegisterSetLock()
{
	PowerSetWakeLock("Register_LOCK");
}

int MobileCountryRegisterSetUnlock()
{
	PowerSetWakeUnLock("Register_LOCK");
}

int MobileCountrySetLivePreviewState(char state)
{
    gs_mcLivePreviewState = state;
    LOGI("live preview state: %d\n", gs_mcLivePreviewState);
    return 0;
}

int MobileCountryCheckIsLivePreview(void)
{
    int bLivePreview = 0;
    static time_t startLivingTime = 0;
    
    if (gs_mcLivePreviewState == 1) 
    {
        bLivePreview = 1;
        if (startLivingTime == 0) {
            startLivingTime = time(NULL);
        } else {
            if (time(NULL) >= startLivingTime + MC_LIVE_PREVIEW_MAX_TIME_SEC) {
                bLivePreview = 0;
                LOGW("live preview more than the limit (%ds) time!\n", MC_LIVE_PREVIEW_MAX_TIME_SEC);
            }
        }
    }
    else
    {
        startLivingTime = 0;
        bLivePreview = 0;
    }

    return bLivePreview;
}


/************************************************************************
* 设备相关的回调函数处*
*************************************************************************/
int MobileCountrySdkDeviceCallback(cc_device_cmd_e cmd, void* data, void* user_data)
{
	int *value = (int *)data;
	switch (cmd)
	{
	case CC_CMD_LED_SWITCH:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_LED_SWITCH, status %s\n", __FUNCTION__, __LINE__, cmd, *value == 1 ? "on" : "off");
		break;
	}
	case CC_CMD_REBOOT:
	{
		SystemReboot("yidong CC_CMD_REBOOT");
		printf("%s line(%d) cmd(%d)=CC_CMD_REBOOT\n", __FUNCTION__, __LINE__, cmd);
		break;
	}
	case CC_CMD_PACK_LOGS:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_PACK_LOGS\n", __FUNCTION__, __LINE__, cmd);
		strcpy((char*)data, "/tmp/xxx.log");
		break;
	}
	case CC_CMD_SET_SYSTEM_TIME:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_SYSTEM_TIME, utc time is %lld(ms)\n", __FUNCTION__, __LINE__, cmd, *(cc_uint64*)data);
		break;
	}
	case CC_CMD_GET_BATTERY:
	{
		BATTERY_STATUS_S pstBatStatus;

		SocSubGetBatteryStatus(&pstBatStatus);
		if (pstBatStatus.chargingStatus == BAT_CHARGING)
			*value = (int)BATTERY_STATUS_CHARGING;
		else if (pstBatStatus.chargingStatus == BAT_FULL)
			*value = (int)BATTERY_STATUS_FULL;
		else if (pstBatStatus.chargingStatus == BAT_DISCHARGING)
			*value = (int)BATTERY_STATUS_NORMAL;
		else
			*value = (int)BATTERY_STATUS_NULL;
			
		printf("%s line(%d) cmd(%d)=CC_CMD_GET_BATTERY battery=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_GET_BATTERY_PERCENT:
	{
		BATTERY_STATUS_S pstBatStatus;

		SocSubGetBatteryStatus(&pstBatStatus);
		*value = pstBatStatus.capacity;
		//*value = 60;
		printf("%s line(%d) cmd(%d)=CC_CMD_GET_BATTERY battery percent=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_SET_PIR_STATUS:
	{
		char pir_switch;
		DevConfigGetPirSwitch(&pir_switch);
		if (pir_switch != *value)
			DevConfigSetPirSwitch(*value);
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_PIR_STATUS status=%s\n", __FUNCTION__, __LINE__, cmd, *value == 1 ? "on" : "off");
		break;
	}
	case CC_CMD_DEV_INACTIVE:         //建议进入休眠，设备收到此回调时，需要结合当前设备的状态判断是否需要进入休眠，比如在升级过程中是不能休眠的
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_DEV_INACTIVE camera will sleep\n", __FUNCTION__, __LINE__, cmd);
		//PowerSetSocSleepTime(1, 0);
		/*cc_hb_config config ;
    	memset(&config,0,sizeof(config));
    	if(0 == cc_api_suspend(&config))   //获取保活服务器信???    	{
        	Doorbell_sleep();  
    	}
    	cc_api_stop();   */                  //主控板下???		
		break;
	}
	case CC_CMD_QR_START:
	{
		break;
	}
	case CC_CMD_QR_RELEASE:
	{
		break;
	}
	case CC_CMD_QR_STOP:
	{
		break;
	}
	case CC_CMD_QR_DATA_START:  //传入扫描到的二维码字符串
	{
		printf("CC_CMD_QR_DATA_START\n");
		int nDataLen = 0;
		char* pQrcodeData = NULL;

		QrcodePopData(&pQrcodeData, &nDataLen);

		if (pQrcodeData)
		{
			memcpy((char *)data, pQrcodeData, nDataLen);
			free(pQrcodeData);
			printf("Get QRCode Result:SUCCESSFUL!!! =========>");
		}
		else
		{
			printf("Get QRcode Result:Unidentified !!! =========>");
		}
		break;
	}
	case CC_CMD_QR_DATA_RELEASE:
	{
		printf("CC_CMD_QR_DATA_RELEASE\n");
		break;
	}
	case CC_CMD_QR_DATA_STOP:
	{
		printf("CC_CMD_QR_DATA_STOP\n");
		break;
	}
	case CC_CMD_SET_PIR_SENSITIVITY:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_PIR_SENSITIVITY, value=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_SET_PRIVATE_MODE:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_PRIVATE_MODE, value=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_STREAM_RATELIMIT_STATUS:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_STREAM_RATELIMIT_STATUS, video bps %s\n", __FUNCTION__, __LINE__, cmd, *value ? "normal" : "abnormal");
		break;
	}
	case CC_CMD_SET_SOUNDTRACKING:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_SOUNDTRACKING, value=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_SET_AUTOTRACKING:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_AUTOTRACKING, value=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_PLAY_STATUS:
	{
		printf("%s livepreview status:%d\n", __FUNCTION__, *value);
	#if 0
		if (*value == 1)
		{
			PowerSetWakeLock("livepreview");
			//PowerSetSocSleepTime(1, 180);
		}
		else if (*value == 0)
		{
			PowerSetWakeUnLock("livepreview");
			PowerSetSocSleepTime(1, 15);
		}
    #else
        MobileCountrySetLivePreviewState((char)(*value));
	#endif
		break;
	}
	case CC_CMD_TAMPER_ALARM_STATUS:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_TAMPER_ALARM_STATUS, value=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		char pAlarmSwitch;
		DevConfigGetAlarmSwitch(&pAlarmSwitch);
		if (pAlarmSwitch != *value)
			DevConfigSetAlarmSwitch(*value);
		break;
	}
	case CC_CMD_CLEAR_TAMPER_ALARM:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_CLEAR_TAMPER_ALARM, value=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	default:
		printf("%s: cmd[%d] value[%d] not support\n", __FUNCTION__, cmd,*value);
		break;
	}

	return 0;
}

/************************************************************************
* 视频相关的回调函数处 *
*************************************************************************/
int MobileCountrySdkVideoCallback(cc_video_cmd_e cmd, void* data, void* user_data)
{
	int *value = (int *)data;

	switch (cmd)
	{
	case CC_CMD_SET_NIGHT_MODE:
	{
		int pMode = 0;
		DevConfigGetIrNightMode(&pMode);
		if (pMode != *value)
			DevConfigSetIrNightMode(*value);
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_NIGHT_MODE mode=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	}
	case CC_CMD_SET_ANDTIFLICKER:
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_ANDTIFLICKER freq=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	case CC_CMD_SET_ROTATE:
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_ROTATE angle=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	case CC_CMD_SET_MOTION_DETECTION_REGION:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_MOTION_DETECTION_REGION\n", __FUNCTION__, __LINE__, cmd);
		break;
	}
	case CC_CMD_SET_HD_VIDEO:
	{
		cc_hd_s hd;
		memcpy(&hd, data, sizeof(hd));
		if (hd.hd == 0)
		{
			Doorbell_video_set_HD(0);
			g_doorbell_hd = 0;
		}
		else if (hd.hd == 1)
		{
			Doorbell_video_set_HD(1);
			g_doorbell_hd = 1;
		}
		break;
	}

	default:
		printf("%s cmd[%d] not legality\n", __FUNCTION__, cmd);
	}

	return 0;
}

/************************************************************************
* 声音相关的回调函???*
*************************************************************************/
int MobileCountrySdkAudioCallback(cc_audio_cmd_e cmd, void* data, void* user_data)
{
	int *value = (int*)data;

	switch (cmd)
	{
	case CC_CMD_AUDIO_START:
		printf("%s line(%d) cmd(%d)=CC_CMD_AUDIO_START\n", __FUNCTION__, __LINE__, cmd);
        AudioGetOpsHandle()->talkback_start();
		break;
	case CC_CMD_AUDIO_STOP:
		printf("%s line(%d) cmd(%d)=CC_CMD_AUDIO_STOP\n", __FUNCTION__, __LINE__, cmd);
        AudioGetOpsHandle()->talkback_stop();
		break;
	case CC_CMD_AUDIO_TALK:
		printf("%s line(%d) cmd(%d)=CC_CMD_AUDIO_TALK, len %d\n", __FUNCTION__, __LINE__, cmd, ((cc_buf*)data)->bytes);
		if (((cc_buf*)data)->bytes == 0)
		{
			printf("CC_CMD_AUDIO_TALK stopped!\n");
		}
		else
		{
			int i;
			if (((cc_buf*)data)->bytes > 1024)
			{
				for (i = 0; i < ((cc_buf*)data)->bytes / 1024; i++)
				{
					AudioGetOpsHandle()->talkback_data((unsigned char*)((cc_buf*)data)->buf + i*1024, 1024, AUDIO_TYPE_G711A);
				}

				if (((cc_buf*)data)->bytes%1024 != 0)
					AudioGetOpsHandle()->talkback_data((unsigned char*)((cc_buf*)data)->buf + i*1024, ((cc_buf*)data)->bytes - i*1024, AUDIO_TYPE_G711A);
			}
			else
			{
				AudioGetOpsHandle()->talkback_data((unsigned char*)((cc_buf*)data)->buf, ((cc_buf*)data)->bytes, AUDIO_TYPE_G711A);
			}
		}
		break;
	case CC_CMD_SET_SOUND_DETECTION_SENSITIVITY:
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_SOUND_DETECTION_SENSITIVITY sensitivity=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	case CC_CMD_SET_VOLUME:
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_VOLUME volume=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		#if 1
		PLAY_VOLUME_CONFIG stPlayVol;
		AudioGetOpsHandle()->get_play_volume(&stPlayVol);
		if (*value != stPlayVol.talkbackVol)
		    stPlayVol.talkbackVol = (char)(*value);
			AudioGetOpsHandle()->set_play_volume(stPlayVol);
		#endif
		break;
	case CC_CMD_SET_MIC:
		printf("%s line(%d) cmd(%d)=CC_CMD_SET_MIC,mute=%d\n", __FUNCTION__, __LINE__, cmd, *value);
		break;
	default:
		printf("%s: cmd[%d] not legality\n", __FUNCTION__, cmd);
	}

	return 0;
}

/************************************************************************
* 网络相关的回调函???*
*************************************************************************/
int MobileCountrySdkNetWorkCallback(cc_network_cmd_e cmd, void* data, void* user_data)
{
	cc_wifi *wifi_data = NULL;

	switch (cmd)
	{
	case CC_CMD_GET_WIFI_LIST:
	{
		int i;
		static cc_wifi_s s_wifi_list = {0};
		WIFI_LIST_INFO_S pstWifiListInfo;
		printf("%s line(%d) cmd(%d)=CC_CMD_GET_WIFI_LIST\n", __FUNCTION__, __LINE__, cmd);
		WifiGetListInfo(&pstWifiListInfo);

		s_wifi_list.count = pstWifiListInfo.cnt;
		cc_wifi wifi_list_Buf[pstWifiListInfo.cnt];
		for (i = 0; i < pstWifiListInfo.cnt; i++)
		{
			strcpy(wifi_list_Buf[i].bssid, pstWifiListInfo.astAttrInfo[i].bssid);
			strcpy(wifi_list_Buf[i].ssid, pstWifiListInfo.astAttrInfo[i].ssid);
			strcpy(wifi_list_Buf[i].passwd, pstWifiListInfo.astAttrInfo[i].passwd);
			wifi_list_Buf[i].signal = 5;
			wifi_list_Buf[i].mode = pstWifiListInfo.astAttrInfo[i].mode;
			wifi_list_Buf[i].connected = pstWifiListInfo.astAttrInfo[i].bConnected;
			wifi_list_Buf[i].hidden = pstWifiListInfo.astAttrInfo[i].bHidden;
			wifi_list_Buf[i].signal_level = pstWifiListInfo.astAttrInfo[i].signaLevel;
			wifi_list_Buf[i].noise_level = pstWifiListInfo.astAttrInfo[i].noiseLevel;
		}
		memcpy(s_wifi_list.wifi_list_buf, wifi_list_Buf, sizeof(wifi_list_Buf));
		memcpy(data, &s_wifi_list, sizeof(cc_wifi_s));
	}
		break;

	case CC_CMD_SWITCH_WIFI:
		{
			wifi_data = (cc_wifi*)data;
			printf("get wifi ssid=%s,key=%s,mode=%d\n", wifi_data->ssid, wifi_data->passwd, wifi_data->mode);
			while (AudioGetOpsHandle()->play_file_start(AUDIO_RCVWAVE_SUCCESS, AUDIO_TYPE_MP3, 0) < 0) {
                usleep(100 * 1000);
            }
		#if 0
			if (WifiCheckIsConnected())
				WifiSetDisconnect();
		#endif

#if 0
            WIFI_ENCRYPT_TYPE_E enEncryptType = WIFI_ENCRYPT_NULL;

            switch (wifi_data->mode)
            {
                case CC_WIFI_MODE_NULL:
                    enEncryptType = WIFI_ENCRYPT_NULL;
                    break;
                case CC_WIFI_MODE_OPEN:
                    enEncryptType = WIFI_ENCRYPT_OPEN;
                    break;
                case CC_WIFI_MODE_WPA:
                    enEncryptType = WIFI_ENCRYPT_WPA;
                    break;
                case CC_WIFI_MODE_WPA2:
                    enEncryptType = WIFI_ENCRYPT_WPA2;
                    break;
                case CC_WIFI_MODE_WEP:
                    enEncryptType = WIFI_ENCRYPT_WEP;
                    break;
                case CC_WIFI_MODE_WPA_WPA2:
                    enEncryptType = WIFI_ENCRYPT_WPA_WPA2;
                    break;
                case CC_WIFI_MODE_MAX:
                    enEncryptType = WIFI_ENCRYPT_MAX;
                    break;
            }
            WifiSetConnect(wifi_data->ssid, wifi_data->passwd, enEncryptType);
#else
            if (strlen(wifi_data->passwd)) {
                WifiSetConnect(wifi_data->ssid, wifi_data->passwd, WIFI_ENCRYPT_WPA_WPA2);
            } else {
                WifiSetConnect(wifi_data->ssid, wifi_data->passwd, WIFI_ENCRYPT_OPEN);
            }
#endif

			//连接WIFI，连接成功返??????如果连接失败，需要返???
			
		#if 0
			for (int i = 0; i < 120; i++)
			{//120秒连不上就认定是失败
				if (WifiCheckIsConnected())
				{
					break;
				}
				sleep(1);
			}
		#endif
			if (WifiCheckIsConnected())
			{
				printf("\n\n\nwifi connected\n\n\n\n");
				QrcodeScanStop();
		    	QrcodeClearData();
				/* wait wan net ok */
				int ret = 0;
				char outIp[32] = "";
				int waitCnt = 0;
				while (1) {
					#if 1
					ret = NetLiteosGetAddrInfo("www.baidu.com", outIp);
					if (strlen(outIp) > 0) {
						printf("wait wan net ok!!!\n");
						return 0;
					}
					#else
					ping("www.baidu.com");
					if (get_icmp_len())
					{
						printf("wait wan net ok!!!\n");
						return 0;
					}
					#endif
					usleep(100 * 1000);
					if (++waitCnt >= 150) { //15s
						printf("wait wan net ok failed!!!\n");
						g_register_status = 1;
						while (AudioGetOpsHandle()->play_file_start(AUDIO_CONFIG_FAIL, AUDIO_TYPE_MP3, 0) < 0) {
        					 usleep(100 * 1000);
    					}
						sleep(5);
						MobileCountryRegisterSetUnlock();
						return -1;
					}
				}
				return 0;
			}
			else
			{
				printf("\n\n\n\ncan not connect wifi\n\n\n\n");
				QrcodeScanStop();
		    	QrcodeClearData();
				return -1;
			}
		}
		break;

	case CC_CMD_GET_WIFI_DEVICE_NAME:
		memcpy(data, "wlan0", strlen("wlan0"));
		printf("%s line(%d) cmd(%d)=CC_CMD_GET_WIFI_DEVICE_NAME\n", __FUNCTION__, __LINE__, cmd);
		break;

	case CC_CMD_CURRENT_WIFI:
	{
		WIFI_STATUS_INFO_S pstStatusInfo;
	
		WifiGetStatus(&pstStatusInfo);
		wifi_data = (cc_wifi*)malloc(sizeof(cc_wifi));
		printf("CC_CMD_CURRENT_WIFI");
		strcpy(wifi_data->bssid, "8a2593b3cf8b");
		strcpy(wifi_data->ssid, pstStatusInfo.ssid);
		//strcpy(wifi_data->passwd, "12345678");
		wifi_data->signal = pstStatusInfo.signalLevel;
		wifi_data->mode = CC_WIFI_MODE_WPA_WPA2;
		wifi_data->noise_level = 1;
		wifi_data->signal_level = 1;
		wifi_data->connected = 1;
		memcpy(data, wifi_data, sizeof(cc_wifi));
		free(wifi_data);
		wifi_data = NULL;
		printf("CC_CMD_CURRENT_WIFI END!!!!!");
		break;
	}
	default:
		printf("%s: cmd[%d] not legality\n", __FUNCTION__, cmd);
	}

	return 0;
}

/************************************************************************
* 获取设备能力默认值参数，一般和能力集对应，设备注册时会获取，或者设备升级后有新的能力时获取
*************************************************************************/
int MobileCountrySdkGetFeatureDefaultValueCallback(cc_device_default_setting_type_e type, void* value, int len, void* user_data)
{
	printf("%s: line(%d), type:0x%x.\n", __FUNCTION__, __LINE__, type);
	switch (type)
	{
		case CC_DEFAULT_SETTING_TYPE_NIGHT_VISION_MODE:
		{
			strncpy((char*)value, "2", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_PIR_STATUS:
		{
			strncpy((char*)value, "1", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_MOTION_DETECT_STATUS:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_SOUND_DETECT_STATUS:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_PEOPLE_DETECT_STATUS:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_MOTION_DETECT_SENSITIVITY:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_SOUND_DETECT_SENSITIVITY:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_HD_VIDEO:
		{
			strncpy((char*)value, "1", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_PIR_SENSITIVITY:
		{
			strncpy((char*)value, "50", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_LED_STATUS:
		{
			strncpy((char*)value, "1", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_ANTIFLICKER:
		{
			strncpy((char*)value, "50", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_AUTOTRACKING:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_FACE_DETECT_STATUS:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_CAMERAIMAGEROTATE:
		{
			strncpy((char*)value, "0", len);
			break;
		}
		case CC_DEFAULT_SETTING_TYPE_SOUNDTRACKING:
		{
			strncpy((char*)value, "1", len);
			break;
		}
		case CC_DEFAULT_TAMPER_ALARM_STATUS:
		{
			strncpy((char*)value, "1", len);
			break;
		}
		case CC_DEFAULT_TAMPER_ALARM_NOTIFY:
		{
			strncpy((char*)value, "1", len);
			break;
		}
		default:
		{
			*(char*)value = 0;
			break;
		}
	}
	return 0;
}
	
int MobileCountrySdkGetFeatureCapacityCallback(cc_device_capacity_e capacity_type, void* value, int len, void* user_data)
{
	printf("%s: line(%d), type:0x%x.\n", __FUNCTION__, __LINE__, capacity_type);
	return 0;
}
	
int MobileCountrySdkServerStatusCallback(cc_server_status_e server_status, void* data, void* user_data)
{
	switch (server_status)
	{
	case CC_REGISTER_SUCCESS:
		printf("%s line(%d) server_status(%d)=CC_REGISTER_SUCCESS\n", __FUNCTION__, __LINE__, server_status);
		g_register_status = 1;
		while (AudioGetOpsHandle()->play_file_start(AUDIO_CONFIG_SUCCESS, AUDIO_TYPE_MP3, 0) < 0) {
        	 usleep(100 * 1000);
        } 
		McMediaClearData();
		MobileCountryRegisterSetUnlock();
		PowerSetSocSleepTime(1, 20);		
		break;
	case CC_REGISTER_FAIL:
		printf("%s line(%d) server_status(%d)=CC_REGISTER_FAIL\n", __FUNCTION__, __LINE__, server_status);
		g_register_status = 1;
		while (AudioGetOpsHandle()->play_file_start(AUDIO_CONFIG_FAIL, AUDIO_TYPE_MP3, 0) < 0) {
        	 usleep(100 * 1000);
        }
		sleep(5);
		MobileCountryRegisterSetUnlock();
		PowerSetSocSleepTime(AV_TRUE, 5);
		break;
	case CC_SERVER_STATUS_OFFLINE:
		printf("%s line(%d) server_status(%d)=CC_SERVER_STATUS_OFFLINE\n", __FUNCTION__, __LINE__, server_status);
		McSetOnlineState(0);
		break;
	case CC_SERVER_STATUS_ONLINE:
		printf("%s line(%d) server_status(%d)=CC_SERVER_STATUS_ONLINE\n", __FUNCTION__, __LINE__, server_status);
		McSetOnlineState(1);
		break;
	case CC_SERVER_STATUS_DEVICE_REMOVED:
		printf("%s line(%d) server_status(%d)=CC_SERVER_STATUS_DEVICE_REMOVED\n", __FUNCTION__, __LINE__, server_status);
		WifiSetDefaultConfig();
		cc_api_factoryreset();
		DevConfigSetDefault();
		
		PowerSetSocSleepTime(AV_TRUE, 1);
		printf("UNBOUND!!!\n");
		break;
	default:
		printf("%s: server_status[%d] not legality\n", __FUNCTION__, server_status);
	}

	return 0;
}
	
int MobileCountrySdkUpgradeCallback(cc_upgrade_cmd_e cmd, void* data, void* user_data)
{
	cc_upgrade_info *ccinfo = (cc_upgrade_info*)data;
	cc_update_recieve_buf *recive_buf = (cc_update_recieve_buf*)data;
	static cc_uint64 pkg_size = 0;
	static char md5sum[128] = {0};
	static cc_uint64 total_size = 0;
	static int yd_updating = 0;
	switch (cmd)
	{
	case CC_CMD_UPGRADE_INFO:
		pkg_size = 0;
		memset(md5sum, 0, sizeof(md5sum));
		printf("%s line(%d) cmd(%d)=CC_CMD_UPGRADE_INFO,pkg_size=%lld,pkg_type=%d,md5=%s\n", __FUNCTION__, __LINE__, cmd, ccinfo->pkg_size, ccinfo->pkg_type, ccinfo->filemd5);
		printf("pkg_url:%s\n", ccinfo->url);
		printf("pkg_md5:%s\n", ccinfo->filemd5);
		printf("pkg_size:%lld\n", ccinfo->pkg_size);
		total_size = ccinfo->pkg_size;
		strcpy(md5sum,ccinfo->filemd5);
		writeUpgradeInfo((const char*)ccinfo->url,(const char*)ccinfo->filemd5,ccinfo->pkg_size);
		remove(UPGRADE_FILE);
		//UpgradeInit(7 * 1024 * 1024);
		UpgradeInit(ccinfo->pkg_size + 1);
		if (access((char*)UPGRADE_FILE, 0) == -1) {
			fp = fopen((char*)UPGRADE_FILE, "wb");
		}
		PowerSetWakeLock("yd_updating");
		break;

	case CC_CMD_UPGRADE_DOWNLOAD:
		pkg_size += recive_buf->size;
		writefile_callback(recive_buf->buf, 1, recive_buf->size, (void *)UPGRADE_FILE);
		if (pkg_size != 0 &&  pkg_size == total_size)
		{
			printf("ccinfo->pkg_size %d\n", total_size);
			sync();
			fclose(fp);
			fp = NULL;
		}
		printf("%s line(%d) cmd(%d)=CC_CMD_UPGRADE_DOWNLOAD,size=%lld\n", __FUNCTION__, __LINE__, cmd, recive_buf->size);
		break;

	case CC_CMD_UPGRADE_EXECUTE:
	{
		int ret = 0;
		printf("%s line(%d) cmd(%d)=CC_CMD_UPGRADE_EXECUTE, download size = %lld\n", __FUNCTION__, __LINE__, cmd, pkg_size);	
		ret = UpgradeRun(UPGRADE_FILE);	
		UpgradeDeinit();
		PowerSetWakeUnLock("yd_updating");
		UpgradeRecoverySetState(0);
		SystemReboot("yd update success");
//		PowerSetSocSleepTime(1, 10);
//		if (ret < 0)
//		{
//			LOGE("%s line(%d) cmd(%d)=CC_CMD_UPGRADE_EXECUTE, upgrade error\n", __FUNCTION__, __LINE__);
//			return -1;
//		}
		
		/*char UpgradeFilePath[150] = { 0 };
		char strMd5sum[64] = {0};
		GetMd5Value(UPGRADE_FILE, strMd5sum);
		pkg_size = 0;
		if (0 == strcmp(strMd5sum, md5sum))
		{
			printf("MD5 OK OK OK OK !!!!!!!!!!!!!!!!!!!!!!!!!");
			sprintf(UpgradeFilePath, "/app/upgradeTool  %s", UPGRADE_FILE);
			printf("%s\n", UpgradeFilePath);
			//execl("/bin/sh", "sh", "-c", UpgradeFilePath, (char*)0);
			UpgradeRun(UPGRADE_FILE);
			UpgradeDeinit();
			printf("%s line(%d) cmd(%d)=CC_CMD_UPGRADE_EXECUTE, download size = %lld\n", __FUNCTION__, __LINE__, cmd, pkg_size);
		}
		else
		{
			remove(UPGRADE_FILE);
			return -1;
		}*/
		break;
	}
	case  CC_CMD_UPGRADE_DOWNLOAD_FAIL:
	{
		printf("%s line(%d) cmd(%d)=CC_CMD_UPGRADE_DOWNLOAD_FAIL\n", __FUNCTION__, __LINE__, cmd);
		if (fp)
		{
			fclose(fp);
		}
		UpgradeRecoveryStart(UPGRADE_STATUS_DOWNLOAD_FAIL);
	}	
	default:
		printf("%s: cmd[%d] not legality\n", __FUNCTION__, cmd);
	}
	return 0;
}
	
int MobileCountrySdkStoragePartitionInfoCallback(cc_storage_partition_info list[], int *max)
{
	int i = 0;
	INT64 nTotalmem = 0, nRemainmem = 0;
	if (list == NULL) {
		*max = 1;
		return 0;
	}

	for (i = 0; i < *max; i++) {
		char name[15] = { 0 };
		int ret = 0;
		if (access("/dev/mmcblk0", F_OK) == 0)
		{ 
			//ret = file_sys_get_cap_bit(&nTotalmem, &nRemainmem);
			if (ret != -1)
			{
				if (access("/dev/mmcblk0p1", F_OK) == 0)
				{
					sprintf(name, "/dev/mmcblk0p1");
				}
				else
				{
					sprintf(name, "/dev/mmcblk0");
				}
			}
			else
			{
				sprintf(name, "/dev/mmcblk0");
			}
		}
		else
		{
			sprintf(name, "/dev/mmcblk0p1");
		}
		

		strncpy(list[i].name, name, sizeof(list[i].name));
		strncpy(list[i].fs, "vfat", sizeof(list[i].fs));

		list[i].total = nTotalmem;
		list[i].remain = nRemainmem;
	}
	*max = i;
	return 0;
}
	
int MobileCountrySdkStorageFormatCallback(void)
	//static int demo_cc_storage_format()
{
	printf("format sdcard !\n");
	return SdFormat();
	//return 0;
}
	
#ifdef __cplusplus
}
#endif
